﻿#include "qfilecache.h"
#include <QMutexLocker>
#include <QThread>

QFileCache* QFileCache::instance = nullptr;
static QMutex fileCacheMutex;

QFileCache *QFileCache::getInstance()
{
    if(!instance){
        QMutexLocker locker(&fileCacheMutex);
        if(!instance){
           instance = new  QFileCache();
        }
    }
    return instance;
}

int QFileCache::writeData(QString filePath, uint64_t seek, char *buffer, int bufferLen)
{
    int res = -1;
    fileCacheMapMutex.lock();
    if(fileCacheMap.find(filePath) != fileCacheMap.end()){
        if(fileCacheMap[filePath]->file.seek(seek)){
            res = fileCacheMap[filePath]->file.write(buffer,bufferLen);
        }else{
            res = -2;
        }
    }else{
        FileCacheObiect *fileCacheObiect = new FileCacheObiect();
        fileCacheObiect->file.setFileName(filePath);
        fileCacheObiect->file.open(QFile::ReadWrite | QFile::Append);
        fileCacheObiect->lastVisitTime = QDateTime::currentDateTime();
        fileCacheMap.insert(filePath,fileCacheObiect);
    }
    fileCacheMapMutex.unlock();
    return res;
}

int QFileCache::readData(QString filePath, uint64_t seek, char *buffer, int bufferLen)
{
    int res = -1;
    fileCacheMapMutex.lock();
    if(fileCacheMap.find(filePath) != fileCacheMap.end()){
        if(fileCacheMap[filePath]->file.seek(seek)){
            res = fileCacheMap[filePath]->file.read(buffer,bufferLen);
        }else{
            res = -2;
        }
    }else{
        FileCacheObiect *fileCacheObiect = new FileCacheObiect();
        fileCacheObiect->file.setFileName(filePath);
        fileCacheObiect->file.open(QFile::ReadWrite | QFile::Append);
        fileCacheObiect->lastVisitTime = QDateTime::currentDateTime();
        fileCacheMap.insert(filePath,fileCacheObiect);
    }
    fileCacheMapMutex.unlock();
    return res;
}

QFileCache::QFileCache()
{
    timeout = 60 * 60;
    fileCacheRecoveryRun = true;
    fileCacheRecoveryThread = std::thread(&QFileCache::fileCacheRecovery,this);
}

QFileCache::~QFileCache()
{
    fileCacheRecoveryRun = false;
    if(fileCacheRecoveryThread.joinable()){
        fileCacheRecoveryThread.join();
    }
}

void QFileCache::fileCacheRecovery()
{
    while (fileCacheRecoveryRun) {
        fileCacheMapMutex.lock();
        for(QMap<QString,FileCacheObiect*>::iterator it = fileCacheMap.begin();it != fileCacheMap.end() ;it++){
            if(it.value()->lastVisitTime.secsTo(QDateTime::currentDateTime()) > timeout){
                if(it.value()->file.isOpen()){
                    it.value()->file.close();
                }
                fileCacheMap.remove(it.key());
            }
        }
        fileCacheMapMutex.unlock();
        QThread::msleep(10000);
    }
}

int QFileCache::getTimeout() const
{
    return timeout;
}

void QFileCache::setTimeout(int value)
{
    timeout = value;
}
